<script setup>
import { ref } from 'vue'
import Panel from '@/volt/Panel.vue'
import Button from '@/volt/Button.vue'
import Card from '@/volt/Card.vue'
import InputText from '@/volt/InputText.vue'
import Divider from '@/volt/Divider.vue'

import Slider from '@/volt/Slider.vue'
import DataTable from '@/volt/Datatable.vue'
import Column from 'primevue/column'
import Image from 'primevue/image'
import Tag from 'primevue/tag'
import Toast from 'primevue/toast'
import { useToast } from 'primevue/usetoast'
const toast = useToast()

// 输入目录路径
const inputPath = ref('')
// 输出目录路径
const outputPath = ref('')

// 压缩质量（整数：1-10）
const quality = ref(7)
// loading状态
const loading = ref(false)
// 图片列表数据源
const dataSource = ref([])

// 获取文件路径中的文件名
function getFileName(path) {
  return path.split(/[/\\]/).pop()
}

// 格式化文件大小
function formatFileSize(bytes) {
  if (!bytes) return '-'
  bytes = parseInt(bytes, 10)
  if (bytes >= 1024 * 1024) {
    return (bytes / (1024 * 1024)).toFixed(2) + ' MB'
  } else if (bytes >= 1024) {
    return (bytes / 1024).toFixed(2) + ' KB'
  } else {
    return bytes + ' B'
  }
}

// 计算压缩比例
function calcCompressPercent(row) {
  const original = parseInt(row.fileSize, 10)
  const compressed = parseInt(row.compressFileSize, 10)
  const percent = (((compressed - original) / original) * 100).toFixed(2)
  return `${percent}%`
}

// 点击设置输入目录按钮
function handleSetInputPath() {
  // 通过preload接收主进程返回的目录图片文件列表
  dataSource.value = []
  window.api.readDirImages({
    callback: (event, info) => {
      console.log('渲染进程：接收主进程返回的目录图片文件列表：', info)
      // 如果用户取消了选择目录，则不进行任何操作
      if (info.canceled) return
      // 设置输入目录
      inputPath.value = info.filePaths[0] || ''
      // 设置扫描出来的图片列表
      dataSource.value = info.fileList.map((fileInfo, index) => ({
        key: index,
        // 文件路径
        filePath: fileInfo.filePath,
        // 文件大小（字节数）
        fileSize: fileInfo.fileSize,
        // 图片尺寸
        imageSize: fileInfo.imageSize,
        // 压缩后文件大小（初始为null）
        compressFileSize: null,
        // 压缩比例（初始为null）
        compressPercent: null,
        // 状态（0=未开始, 1=压缩中, 2=压缩完成，3=压缩失败）
        status: 0
      }))
      console.log(dataSource.value)
    },
    data: {
      msg: '演示渲染进程向主进程传递数据'
    }
  })
}

// 点击设置输出目录按钮
function handleSetOutputPath() {
  // 通过preload接收主进程返回的目录路径
  window.api.chooseDir({
    callback: (event, info) => {
      // 如果用户取消了选择目录，则不进行任何操作
      if (info.canceled) return
      // 设置输出目录
      outputPath.value = info.filePaths[0] || ''
    }
  })
}

// 开始压缩
async function handleStartCompress() {
  // 如果正在压缩或者没有图片列表，则不执行
  if (loading.value === true || dataSource.value.length === 0) return
  // 如果没有设置输出目录，则不执行
  if (!outputPath.value || outputPath.value === '') {
    toast.add({ severity: 'info', summary: '温馨提醒', detail: '请设置输出目录', life: 3000 })
    return
  }
  if (outputPath.value === inputPath.value) {
    toast.add({
      severity: 'info',
      summary: '温馨提醒',
      detail: '输出目录不能与输入目录相同',
      life: 3000
    })
    return
  }

  // 置为loading态
  loading.value = true

  // 逐个处理dataSource中的图片
  for (let index = 0; index < dataSource.value.length; index++) {
    const item = dataSource.value[index]
    // 更新该条数据的状态为“压缩中”
    dataSource.value[index].status = 1
    // 交给主进程进行图片处理
    const result = await window.api.imageCompress({
      inputPath: item.filePath,
      outputDir: outputPath.value,
      quality: quality.value * 10
    })

    if (result.success) {
      // 压缩成功，更新状态和压缩后文件大小
      dataSource.value[index].status = 2
      dataSource.value[index].compressFileSize = result.compressFileSize
    } else {
      // 压缩失败，更新状态
      dataSource.value[index].status = 3
    }
    // 全部执行执行后的处理
    if (index === dataSource.value.length - 1) {
      // 处理成功的数量
      let successCount = 0
      // 处理失败的数量
      let failCount = 0
      // 累计成功和失败的数量
      for (let i = 0; i < dataSource.value.length; i++) {
        if (dataSource.value[i].status === 2) {
          successCount++
        } else if (dataSource.value[i].status === 3) {
          failCount++
        }
      }
      // 弹出处理结果通知框
      toast.add({
        severity: 'success',
        summary: '压缩完成',
        detail: `成功 ${successCount} 个，失败 ${failCount} 个。`,
        life: 5000
      })
    }
  }
  // 取消loading状态
  loading.value = false
}
</script>

<template>
  <div class="w-full">
    <Panel header="选择目录" class="w-full">
      <!-- 请选择需要压缩图片的目录，程序会递归处理该目录下的所有图片文件。 -->
      <div class="block mb-2">
        <span class="font-bold mr-2">设置输入目录</span>
        <Button
          label="设置输入目录"
          icon="pi pi-folder-open"
          size="small"
          @click="handleSetInputPath"
        />
      </div>
      <InputText v-show="inputPath" fluid :value="inputPath" disabled />
      <Divider type="dotted" />
      <div class="p-0">
        <!-- 请选择压缩后图片的输出目录，若不设置则覆盖原图。 -->
        <div class="block mb-2">
          <span class="font-bold mr-2">设置输出目录</span>
          <Button
            label="设置输出目录"
            icon="pi pi-folder-open"
            size="small"
            @click="handleSetOutputPath"
          />
        </div>
        <InputText v-show="outputPath" fluid :value="outputPath" disabled />
      </div>
      <Divider type="dotted" />
      <div class="mt-4 w-full flex flex-col gap-2">
        <p class="m-0 text-surface-600 dark:text-surface-400">
          <span class="font-bold">设置图片压缩质量（1-10）：</span>
          <span class="text-surface-600 dark:text-surface-400">当前质量：{{ quality }}</span>
        </p>
        <Slider v-model="quality" :min="1" :max="10" :step="1" class="w-full mt-2" />
        <!-- <Slider v-model="quality" class="w-56" /> -->
      </div>
    </Panel>

    <div class="mt-4">
      <Button
        label="开始压缩"
        icon="pi pi-check"
        :loading="loading"
        :disabled="dataSource.length === 0"
        class="w-full"
        @click="handleStartCompress"
      />
    </div>

    <div v-if="dataSource.length > 0" class="mt-6">
      <Panel header="压缩结果" class="w-full">
        <Card class="card mt-4">
          <template #content>
            <DataTable :value="dataSource" size="small" table-style="min-width: 50rem">
              <Column field="fileName" header="文件名">
                <template #body="slotProps">
                  <span>{{ getFileName(slotProps.data.filePath) }}</span>
                </template>
              </Column>
              <Column field="preview" header="预览">
                <template #body="slotProps">
                  <Image
                    preview
                    :src="'file:///' + slotProps.data.filePath"
                    alt="preview"
                    width="180"
                    class="w-16 h-16 object-cover"
                  />
                </template>
              </Column>
              <!-- 图片尺寸 -->
              <Column field="size" header="图片尺寸">
                <template #body="slotProps">
                  <span
                    >{{ slotProps.data.imageSize.width }} x
                    {{ slotProps.data.imageSize.height }}</span
                  >
                </template>
              </Column>
              <Column field="originalSize" header="原始大小">
                <template #body="slotProps">
                  <span>{{ formatFileSize(slotProps.data.fileSize) }}</span>
                </template>
              </Column>
              <Column field="compressedSize" header="压缩后大小">
                <template #body="slotProps">
                  <span>{{ formatFileSize(slotProps.data.compressFileSize) }}</span>
                </template>
              </Column>
              <Column field="status" header="压缩比例">
                <template #body="slotProps">
                  <Tag v-if="slotProps.data.status === 0" severity="secondary"> 未开始 </Tag>
                  <Tag v-else-if="slotProps.data.status === 1" severity="info"> 压缩中 </Tag>
                  <Tag v-else-if="slotProps.data.status === 2" severity="success">
                    {{ calcCompressPercent(slotProps.data) }}
                  </Tag>
                  <Tag v-else-if="slotProps.data.status === 3" severity="danger"> 压缩失败 </Tag>
                </template>
              </Column>
            </DataTable>
          </template>
        </Card>
      </Panel>
    </div>

    <Toast />
  </div>
</template>

<style scoped>
.card {
  /* background: #fff; */
  /* border: var(--card-border); */
  /* border-radius: 10px;
  margin-bottom: 1rem;
  padding: 2rem; */
}
</style>
